package com.zsw.dubbo.console;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 控制台指令对象
 * 
 * @author daze
 * 
 */
public class ConsoleB {
	private String className;// 类名
	@SuppressWarnings("rawtypes")
	private Class clazz;// 类对象

	private String methodName;// 方法名;
	private Method method;// 方法
	private Class<?>[] args;// 参数

	private String fieldName;// 属性名
	private Field field;// 属性对象

	private Object obj;// 类实例化对象
	private String message;// 类信息
	private int line;

	public ConsoleB() {
	}

	public ConsoleB(String clazzName, String methodName)
			throws SecurityException, NoSuchMethodException,
			NoSuchFieldException {
		this.init(initClass(clazzName), methodName, methodName);
	}

	@SuppressWarnings("rawtypes")
	public ConsoleB(String clazzName, String methodName, Class... classes)
			throws SecurityException, NoSuchMethodException {
		this.init(initClass(clazzName), methodName, methodName, classes);
	}

	@SuppressWarnings("rawtypes")
	public ConsoleB(Class clazz, String methodName) throws SecurityException,
			NoSuchMethodException, NoSuchFieldException {
		this.init(clazz, methodName, methodName);
	}

	@SuppressWarnings("rawtypes")
	public ConsoleB(Class clazz, String methodName, String fieldName)
			throws SecurityException, NoSuchMethodException,
			NoSuchFieldException {
		this.init(clazz, methodName, fieldName);
	}

	public ConsoleB(Object o, String methodName, String fieldName)
			throws SecurityException, NoSuchMethodException {
		this.init(o, methodName, fieldName);
	}

	public ConsoleB(Object o, String methodName) throws SecurityException,
			NoSuchMethodException {
		this.init(o, methodName, methodName);
	}

	public ConsoleB(Object o, String methodName, Class<?>... classes)
			throws SecurityException, NoSuchMethodException {
		this.init(o, methodName, methodName, classes);
	}

	private Class<?> initClass(String clazzName) {
		this.className = clazzName;
		try {
			return Class.forName(clazzName);
		} catch (ClassNotFoundException e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public void init(Object obj, String methodName, String fieldName,
			Class<?>... classes) throws SecurityException,
			NoSuchMethodException {
		this.methodName = methodName;
		this.fieldName = fieldName;
		this.args = classes;
		if (obj != null) {
			try {
				if (obj.getClass() == Class.class) {
					this.clazz = (Class<?>) obj;
				} else {
					this.clazz = obj.getClass();
					this.obj = obj;
				}
				Object o = null;
				this.className = clazz.getName();
				this.method = clazz.getMethod(methodName, classes);
				this.field = clazz.getField(fieldName);
				if (Modifier.isStatic(this.field.getModifiers())) {
					o = this.field.get(this.clazz);
				} else {
					if (obj.getClass() == Class.class) {
						this.obj = this.clazz.newInstance();
					}
					o = this.field.get(this.obj);
				}
				this.message = o != null ? o.toString() : "未能成功获取命令说明";
			} catch (NoSuchFieldException e) {
				if (this.method.isAnnotationPresent(Message.class)) {
					Message message = this.method.getAnnotation(Message.class);
					this.message = message.value();
				} else {
					this.message = "未能成功获取命令说明";
				}
			} catch (Exception e) {
				this.message = "未能成功获取命令说明";
			}
		} else {
			this.message = "命令嵌入错误! 目标类没有找到";
		}
	}

	public Object send(String... args) throws IllegalArgumentException,
			IllegalAccessException, InvocationTargetException {
		return send(obj, args);
	}

	@SuppressWarnings("unchecked")
	public Object send(Object o, String... args)
			throws IllegalArgumentException, IllegalAccessException,
			InvocationTargetException {
		if (method == null) {
			try {
				Class<?>[] cArgs = new Class[args.length];
				for (int i = 0; i < cArgs.length; i++) {
					cArgs[i] = args[i].getClass();
				}
				this.method = clazz.getMethod(methodName, cArgs);
			} catch (Exception e) {
				// e.printStackTrace();
				throw new NullPointerException("方法未找到,请重新确认方法名称与参数\n"
						+ e.getMessage());
			}
		}
		Object retO = null;
		if (Modifier.isStatic(method.getModifiers())) {
			o = null;
		}
		if (args == null || args.length == 0) {
			retO = method.invoke(o);
		} else {
			retO = method.invoke(o, (Object[]) args);
		}
		return retO;
	}

	public Class<?> getClazz() {
		return clazz;
	}

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	// public Field getField() {
	// return field;
	// }
	//
	// public void setField(Field field) {
	// this.field = field;
	// try {
	// this.message = (String) this.field.get(clazz);
	// } catch (Exception e) {
	// this.message = "未能成功获取命令说明";
	// }
	// }

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}

	public String getFieldName() {
		return fieldName;
	}

	public void setFieldName(String fieldName) {
		this.fieldName = fieldName;
	}

	public Field getField() {
		return field;
	}

	public void setField(Field field) {
		this.field = field;
	}

	public Object getObj() {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj;
	}

	public int getLine() {
		return line;
	}

	public void setLine(int line) {
		this.line = line;
	}

	public Class<?>[] getArgs() {
		return args;
	}

	public void setArgs(Class<?>[] args) {
		this.args = args;
	}

	@Target({ ElementType.METHOD })
	@Retention(RetentionPolicy.RUNTIME)
	public @interface Message {
		String value();

		int line() default 0;
	}
}
